package com.airlines.base.config.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.airlines.base.config.jsr303.ValidateUtil;
import com.airlines.base.config.response.ResponseResult;
import com.airlines.base.config.response.ResponseResultBuilder;

import cn.mercury.utils.JsonUtils;

/**
 * @author xxxx
 * @date 2018年6月1日 
 * @description controller 增强器,用于控制全局 @RequestMapping 注解的方法上。
 */
@ControllerAdvice
public class MyControllerAdvice {
	private static final Logger logger = LoggerFactory.getLogger(MyControllerAdvice.class);
	/**
     * 把值绑定到Model中，使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("author", "xxxx");
    }
    
    /**
     * 应用到所有@RequestMapping注解方法，在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
	    //Date格式绑定	
    	binder.registerCustomEditor(Date.class, new MyDatePropertyEditorSupport());
    	
    	//DateTime格式绑定好像不生效，如何解决 2018年6月6日15:08:01 xxxx
    	//binder.registerCustomEditor(DateTime.class, new MyDateTimePropertyEditorSupport());
    	
    	//可继续扩展其他格式的绑定
    }
    
    
    /**
     * bean校验未通过异常
     * @throws IOException 
     *
     * @see javax.validation.Valid
     * @see org.springframework.validation.Validator
     */
    @ExceptionHandler(Exception.class)
    public void exceptionHandler(Exception e,HttpServletRequest request,HttpServletResponse response) throws IOException{
    	logger.error("全局异常处理：{}",getTrace(e));
    	
    	String errorMessage  = "";
    	int status  = 0; 
    	if(e instanceof BindException || e instanceof MethodArgumentNotValidException){
    		BindingResult  result = ((BindException) e).getBindingResult();
    		errorMessage = ValidateUtil.getFileErrorMessage(result);
    		status = HttpStatus.BAD_REQUEST.value();
    	}else if(e instanceof ServletRequestBindingException){
    		status = HttpStatus.BAD_REQUEST.value();
    		errorMessage = e.getMessage();
    		
    	}else if(e instanceof NoHandlerFoundException){
    		status = HttpStatus.NOT_FOUND.value();
    		errorMessage = e.getMessage();
    	}else{
    		status = HttpStatus.INTERNAL_SERVER_ERROR.value();
    		errorMessage = e.getMessage();
    	}
    	
    	
    	ResponseResult<String> responseResult = ResponseResultBuilder.errorResult(null, errorMessage,String.valueOf(status));
    	response.setStatus(status);  
    	response.getWriter().println(JsonUtils.toJson(responseResult));
    }

    
    private String getTrace(Throwable t) {
		StringWriter stringWriter = new StringWriter();
		PrintWriter writer = new PrintWriter(stringWriter);
		t.printStackTrace(writer);
		StringBuffer buffer = stringWriter.getBuffer();
		return buffer.toString();
	}
}
